package com.ysstech.system.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysstech.common.entity.Menu;
import com.ysstech.common.entity.Region;
import com.ysstech.common.entity.Role;
import com.ysstech.common.exception.BusinessException;
import com.ysstech.common.entity.TreeNode;
import com.ysstech.system.mapper.MenuMapper;
import com.ysstech.common.entity.User;
import com.ysstech.system.mapper.RegionMapper;
import com.ysstech.system.service.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * <p>
 * 菜单服务实现类
 * </p>
 *
 * @author lishuangliang
 * @since 2020-09-11
 */
@Slf4j
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Autowired
    private RegionMapper regionMapper;

    /**
     * 加载菜单树
     *
     * @param user
     * @return
     * @throws Exception
     */
    public List<TreeNode> queryUserMenu(User user) throws Exception {
        List<TreeNode> listUserMenu = new ArrayList<>();
        if (null == user) {
            throw new BusinessException("获取用户的菜单失败，请稍后重试！");
        }
        List<TreeNode> list = this.queryAllMenu(false); //所有菜单，不包含按钮
        listUserMenu.addAll(this.getMenuTree(user, list));
        return listUserMenu;
    }

    //用户拥有的菜单权限
    private List<TreeNode> getMenuTree(User user, List<TreeNode> list) {
        List<TreeNode> listNew = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return listNew;
        }
        for (TreeNode treeNode : list) {  //循环菜单匹配
            if (null == treeNode || !"1".equals(treeNode.getTarget())) { //菜单类型不是显示的菜单的
                continue;
            }
            for (Role role : user.getRoles()) { //循环角色匹配菜单
                if (null == role) {
                    continue;
                }
                for (Menu ent : role.getListMenu()) { //角色的菜单和查询出来的菜单匹配
                    if (null == ent || !treeNode.getId().equals(ent.getId())) {
                        continue;
                    }
                    List<TreeNode> children = this.getMenuTree(user, treeNode.getChildren());
                    if (null == children || children.size() == 0) {
                        treeNode.setState("open");
                    }
                    treeNode.setChildren(children);
                    listNew.add(treeNode);
                }
            }
        }
        return listNew;
    }


    /**
     * 加载菜单树
     *
     * @param region 是否包含菜单
     * @return
     * @throws Exception
     */
    public List<TreeNode> queryAllMenu(boolean region) throws Exception {
        List<TreeNode> list = new ArrayList<>();
        list.addAll(this.getTreeNode("0", region));
        return list;
    }

    /**
     * 递归查询菜单信息的方法
     *
     * @param parentMenuId
     * @param region       是否包含菜单
     * @return
     * @throws Exception
     */
    public List<TreeNode> getTreeNode(String parentMenuId, boolean region) throws Exception {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("PARENT_ID", parentMenuId);
        wrapper.orderByAsc("SEQUENCE");
        List<Menu> menus = this.list(wrapper);
        if (menus == null || menus.size() == 0) {
            return null;
        }
        List<TreeNode> list = new ArrayList<>();
        for (Menu menu : menus) {
            if (null == menu) {
                continue;
            }
            TreeNode treeNode = menuToNode(menu);
            List<TreeNode> children = getTreeNode(menu.getId(), region);
            if (region) { //添加菜单
                // 每个菜单都查询是不是对应的按钮信息，如果有就添加进来
                QueryWrapper<Region> wrapperRegion = new QueryWrapper<>();
                wrapperRegion.eq("MENU_ID", menu.getId());
                wrapperRegion.orderByAsc("SEQUENCE");
                List<Region> regionList = regionMapper.selectList(wrapperRegion);
                if (null == children) {  //最后一级
                    children = new ArrayList<>();
                }
                if (null != regionList && regionList.size() > 0) {
                    children.addAll(regionToNode(regionList));
                }
            }
            if (null == children || children.size() == 0) {
                treeNode.setState("open");  // 没有子节点的
            }
            treeNode.setChildren(children);
            list.add(treeNode);
        }
        return list;
    }

    /**
     * 将业务功能转化成TreeNode
     */

    protected TreeNode menuToNode(Menu menu) {
        TreeNode node = new TreeNode();
        node.setId(menu.getId());
        node.setText(menu.getName());
        node.setUrl(menu.getUrl());
        node.setIconCls(menu.getIcon());
        node.setState("closed");
        node.setChecked(false);
        node.setMenuLevel(menu.getLevel());
        node.setPId(menu.getParentId());
        node.setAttributes("menu");
        node.setTarget(menu.getType());
        return node;
    }

    /**
     * 将业务功能转化成zTreeNode
     */
    protected List<TreeNode> regionToNode(List<Region> regionList) {
        List<TreeNode> list = new ArrayList<>();
        for (Region region : regionList) {
            TreeNode node = new TreeNode();
            node.setId(region.getId());
            node.setPId(region.getMenuId());
            node.setText(region.getName());
            node.setIconCls(region.getIcon());
            node.setChecked(false);//是否选中
            node.setState("open");//是否打开
            node.setAttributes("region");
            list.add(node);
        }
        return list;
    }


    /**
     * 查询所有下级机构的机构id集合
     *
     * @param menuId
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenu(String menuId) throws Exception {
        if (StringUtils.isBlank(menuId)) {
            throw new BusinessException("获取机构信息失败，请稍后重试！");
        }
        List<String> menuList = new ArrayList<>();
        List<String> regionList = new ArrayList<>();
        menuList.add(menuId);
        QueryWrapper<Region> wrapperRegion = new QueryWrapper<>();
        wrapperRegion.eq("MENU_ID", menuId);
        List<Region> listRegion = regionMapper.selectList(wrapperRegion);
        for (Region region : listRegion) {
            regionList.add(region.getId());
        }
        List<Menu> listMenu = this.list(); //所有菜单数据
        recursionIds(menuId, menuList, regionList, listMenu);
        if (menuList.size() > 0) {
            this.removeByIds(menuList);
        }
        if (regionList.size() > 0) {
            regionMapper.deleteBatchIds(regionList);
        }
    }

    private void recursionIds(String menuId, List<String> menuList, List<String> regionList, List<Menu> listMenu) {
        for (Menu menu : listMenu) {
            if (!menuId.equals(menu.getParentId())) {
                continue;
            }
            menuList.add(menu.getId());
            QueryWrapper<Region> wrapperRegion = new QueryWrapper<>();
            wrapperRegion.eq("MENU_ID", menu.getId());
            List<Region> listRegion = regionMapper.selectList(wrapperRegion);
            for (Region region : listRegion) {
                regionList.add(region.getId());
            }
            recursionIds(menu.getId(), menuList, regionList,listMenu);
        }
    }

}
